package top.roadvast.network.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @Author 郭泽鹏
 * @Date 2021/12/31 17:25
 * @Version 1.0
 * @Description
 *      TCP通信的服务器端：接收客户端的请求，读取客户端发送的数据，给客户端回写数据
 *      表示服务器的类
 *          java.net.ServerSocket：此类实现服务器套接字
 *
 *      构造方法：
 *          ServerSocket(int port)
 *              创建绑定到指定端口的服务器套接字。
 *
 *      服务器端必须明确一件事情，必须的知道是那个客户端请求的服务器
 *      所以可以使用accept方法获取到请求的客户端对象Socket
 *      成员方法：
 *          Socket accept()：侦听要连接到此套接字并接受它。
 *
 *      实现步骤：
 *          1.创建服务器ServerSocket对象和系统要指定的端口号
 *          2.使用ServerSocket对象中的accept方法获取到请求的客户端对象Socket
 *          3.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象
 *          4.使用网络字节输入流InputStream对象中的方法read，读取客户端发送的数据
 *          5.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象
 *          6.使用网络字节输出流OutputStream对象中的方法write，给客户端回写数据
 *          7.释放资源（Socket、ServerSocket）
 */
public class TCPServer {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;

        try {
            //创建serverSocket，并绑定端口
            serverSocket = new ServerSocket(8083);
            System.out.println("服务器端已启动.");
            while (true) {
                System.out.println("等待客户端连接...");
                //阻塞，等待接收客户端请求套接字
                Socket socket = serverSocket.accept();
                new Thread(() -> {
                    InputStream inputStream = null;
                    OutputStream outputStream = null;
                    try {
                        System.out.println("===========客户端[" + socket.getInetAddress() + ":"
                                + socket.getPort() + "]已连接，正在进行交互===========");
                        //获取输入流
                        inputStream = socket.getInputStream();
                        //缓冲区
                        final byte[] bytes = new byte[1024];
                        //读取客户端数据返回的长度，-1表示已经读完
                        int len = -1;
                        //接收数据，存储在bytes中，然后返回长度
                        while ((len = inputStream.read(bytes)) != -1) {
                            System.out.println("********接收到消息：开始打印到控制台********");
                            //打印客户端数据
                            System.out.println(new String(bytes, 0, len));
                            outputStream = socket.getOutputStream();
                            final String response = "消息已处理";
                            outputStream.write(response.getBytes());
                            System.out.println("+++++已响应消息+++++");
                        }
                        System.out.println("客户端" + socket.getInetAddress() + ":"
                                + socket.getPort() + "已断开.");
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            if (inputStream != null) {
                                inputStream.close();
                            }
                            if (outputStream != null) {
                                outputStream.close();
                            }
                            if (socket != null) {
                                socket.close();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (serverSocket != null) {
                    serverSocket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
